﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;

namespace MvcWiki.Test.Service.WikiNamespaceService
{
    public class GetWikiNamespaceFacts
    {
        [Fact]
        public void Call()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(
                x => x.CanViewNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = service.GetWikiNamespace("Namespace");
        }

        [Fact]
        public void Calls_Repository()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();
            wikiNamespaceRepository.Setup(x => x.GetWikiNamespace("Namespace"));

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(
                x => x.CanViewNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.GetWikiNamespace("Namespace");

            wikiNamespaceRepository.VerifyAll();
        }

        [Fact]
        public void Returns_WikiNamespace()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();
            wikiNamespaceRepository.Setup(x => x.GetWikiNamespace("Namespace")).Returns(wikiNamespace);

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(
                x => x.CanViewNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            Assert.Equal<MvcWiki.Model.WikiNamespace>(wikiNamespace, service.GetWikiNamespace("Namespace"));
        }

        [Fact]
        public void Calls_WikiUserProvider_CanViewNamespace()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();
            wikiNamespaceRepository.Setup(x => x.GetWikiNamespace("Namespace"));

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(
                x => x.CanViewNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.GetWikiNamespace("Namespace");

            wikiUserProvider.Verify(
                x => x.CanViewNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>()));
        }

        [Fact]
        public void Throws_Exception_If_CanViewNamespace_Is_False()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();
            wikiNamespaceRepository.Setup(x => x.GetWikiNamespace("Namespace"));

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(
                x => x.CanViewNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(false);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            Assert.Throws<MvcWiki.Exceptions.AuthorizationException>(
                () => service.GetWikiNamespace("Namespace"));
        }
    }
}
